package com.xique.door.device.hk.service;

import com.alibaba.fastjson.JSONObject;

import com.xique.door.util.RedisUtil;
import com.xique.door.device.hk.bean.dto.OAuth2TokenDTO;
import com.xique.door.device.hk.bean.param.*;
import com.xique.door.device.hk.bean.response.BasicResponse;
import com.xique.door.device.hk.bean.response.DeviceResponse;
import com.xique.door.device.hk.bean.response.GroupResponse;
import com.xique.door.device.hk.bean.response.PersonResponse;
import com.xique.door.util.RestTemplateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.map.SingletonMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * @author caogq
 * @Date: 2021/7/13 14:12
 * @Description:
 */
@Service
@Slf4j
public class HkCommandService {
    private static final String TOKEN_URL = "/oauth/token";
    private static final String OPEN_BASIC_GROUP_ADD = "/api/v1/open/basic/groups/create";
    private static final String OPEN_BASIC_GROUP_GET = "/api/v1/open/basic/groups/get";
    private static final String OPEN_BASIC_DEVICE_ADD = "/api/v1/open/basic/devices/create";
    private static final String OPEN_BASIC_DEVICE_UPDATE = "/api/v1/open/basic/devices/update";
    private static final String OPEN_BASIC_DEVICE_DELETE = "/api/v1/open/basic/devices/delete";
    private static final String OPEN_BASIC_DEVICE_GET = "/api/v1/open/basic/devices/get";
    private static final String OPEN_BASIC_PERSON_ADD = "/api/v1/open/basic/persons/create";
    private static final String OPEN_BASIC_PERSON_UPDATE = "/api/v1/open/basic/persons/update";
    private static final String OPEN_BASIC_PERSON_DELETE = "/api/v1/open/basic/persons/delete";
    private static final String OPEN_BASIC_PERSON_GET = "/api/v1/open/basic/persons/get";


    @Value("${CLIENT_ID}")
    private String clientId;
    @Value("${CLIENT_SECRET}")
    private String clientSecret;
    @Value("${OPEN_URL}")
    private String host;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private RestTemplateUtils restTemplateUtils;


    /**
     * 封装token请求头
     *
     * @return
     */
    public Map<String, String> getTokenHeaders() {
        return new SingletonMap("Authorization", "bearer " + getToken());
    }

    /**
     * 获取token：
     * 1、token未过期：从redis获取
     * 2、token过期：调用hk，存入redis中，并返回
     *
     * @return
     */
    public String getToken() {
        Object obj = redisUtil.get("hk:" + clientId + ":" + clientSecret + ":token");
        if (obj == null) {
            return createToken(clientId, clientSecret);
        }
        String existToken = obj.toString();
        log.info("获取缓存中的token");
        return existToken;

    }

    public String createToken(String clientId, String clientSecret) {
        String url = host + TOKEN_URL;
        Map<String, Object> params = new HashMap<>();
        params.put("client_id", clientId);
        params.put("client_secret", clientSecret);
        params.put("grant_type", "client_credentials");
        OAuth2TokenDTO oAuth2TokenDTO = restTemplateUtils.httpPostFrom(url, params, null, OAuth2TokenDTO.class);

        String token = oAuth2TokenDTO.getAccess_token();
        //token时间为7天，提前3秒设置失效
        redisUtil.set("hk:" + clientId + ":" + clientSecret + ":token", token, oAuth2TokenDTO.getExpires_in() - 3);
        return token;
    }


    /**
     * 添加设备组
     *
     * @param groupAddParam
     */
    public BasicResponse addGroup(GroupAddParam groupAddParam) {

        Map params = JSONObject.parseObject(JSONObject.toJSONString(groupAddParam), Map.class);
        BasicResponse openResult = restTemplateUtils.httpPostJson(host + OPEN_BASIC_GROUP_ADD, params, getTokenHeaders(), BasicResponse.class);
        log.info("addGroup,groupAddParam:{} basicResponse:{}", groupAddParam, openResult);
        return openResult;
    }

    /**
     * 查询设备组是否存在
     *
     * @param groupNo
     * @return
     */
    public GroupResponse getOneGroup(String groupNo) {
        GroupResponse response = restTemplateUtils.httpGetTraditional(host + OPEN_BASIC_GROUP_GET, new SingletonMap("groupNo", groupNo), getTokenHeaders(), GroupResponse.class);
        return response;
    }

    /**
     * 注册设备
     *
     * @param deviceAddParam
     */
    @Async
    public void addDevice(DeviceAddParam deviceAddParam) {
        Map params = JSONObject.parseObject(JSONObject.toJSONString(deviceAddParam), Map.class);
        DeviceResponse result = restTemplateUtils.httpPostJson(host + OPEN_BASIC_DEVICE_ADD, params, getTokenHeaders(), DeviceResponse.class);
        log.info("addDevice,deviceAddParam:{} DeviceResponse:{}" + deviceAddParam + result);
    }

    /**
     * 修改设备名称
     *
     * @param deviceUpdateParam
     * @return
     */
    public BasicResponse updateDevice(DeviceUpdateParam deviceUpdateParam) {

        Map params = JSONObject.parseObject(JSONObject.toJSONString(deviceUpdateParam), Map.class);
        BasicResponse openResult = restTemplateUtils.httpPostJson(host + OPEN_BASIC_DEVICE_UPDATE, params, getTokenHeaders(), BasicResponse.class);
        log.info("addGroup,groupAddParam:{} basicResponse:{}", params, openResult);
        return openResult;
    }

    /**
     * 注销设备
     *
     * @param deviceSerial 设备序列号
     * @return
     */
    public BasicResponse deleteDevice(String deviceSerial) {

        SingletonMap singletonMap = new SingletonMap("deviceSerial", deviceSerial);
        BasicResponse openResult = restTemplateUtils.httpPostFrom(host + OPEN_BASIC_DEVICE_DELETE, singletonMap, getTokenHeaders(), BasicResponse.class);
        log.info("deleteDevice,deviceSerial:{} basicResponse:{}", deviceSerial, openResult);
        return openResult;
    }

    /**
     * 查询设备详情（含设备状态）
     *
     * @param deviceSerial 设备序列号
     * @return
     */
    public DeviceResponse getDeviceDetail(String deviceSerial) {

        SingletonMap singletonMap = new SingletonMap("deviceSerial", deviceSerial);
        DeviceResponse openResult = restTemplateUtils.httpGetTraditional(host + OPEN_BASIC_DEVICE_GET, singletonMap, getTokenHeaders(), DeviceResponse.class);
        log.info("deleteDevice,deviceSerial:{} basicResponse:{}", deviceSerial, openResult);
        return openResult;
    }

    /**
     * 新增人员
     *
     * @param personAddParam
     * @return
     */
    public PersonResponse addPerson(PersonAddParam personAddParam) {

        Map params = JSONObject.parseObject(JSONObject.toJSONString(personAddParam), Map.class);
        PersonResponse openResult = restTemplateUtils.httpPostJson(host + OPEN_BASIC_PERSON_ADD, params, getTokenHeaders(), PersonResponse.class);
        log.info("addPerson,personAddParam:{} PersonResponse:{}", personAddParam, openResult);
        return openResult;
    }

    /**
     * 修改人员
     *
     * @param personUpdateParam
     * @return
     */
    public BasicResponse updatePerson(PersonUpdateParam personUpdateParam) {

        Map params = JSONObject.parseObject(JSONObject.toJSONString(personUpdateParam), Map.class);
        BasicResponse openResult = restTemplateUtils.httpPostJson(host + OPEN_BASIC_PERSON_UPDATE, params, getTokenHeaders(), BasicResponse.class);
        log.info("updatePerson,personUpdateParam:{} basicResponse:{}", personUpdateParam, openResult);
        return openResult;
    }

    /**
     * 删除人员
     *
     * @param employeeNo 员工号
     * @return
     */
    public BasicResponse deletePerson(String employeeNo) {
        BasicResponse openResult = restTemplateUtils.httpPostJson(host + OPEN_BASIC_PERSON_DELETE + "?employeeNo=" + employeeNo, null, getTokenHeaders(), BasicResponse.class);
        log.info("deletePersion,employeeNo:{} basicResponse:{}", employeeNo, openResult);
        return openResult;
    }

    public PersonResponse getPersonDetail(String employeeNo) {

        SingletonMap singletonMap = new SingletonMap("employeeNo", employeeNo);
        PersonResponse openResult = restTemplateUtils.httpGetTraditional(host + OPEN_BASIC_PERSON_GET, singletonMap, getTokenHeaders(), PersonResponse.class);
        log.info("getPersonDetail,employeeNo:{} basicResponse:{}", employeeNo, openResult);
        return openResult;
    }


}
